package com.fsserver.facedetection;

import com.fsserver.facedetection.controller.FaceDetectionController;
import com.fsserver.facedetection.service.FaceDetectionService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.*;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import static org.junit.jupiter.api.Assertions.*;

/**
 * 人脸检测应用集成测试
 * 
 * @author fsserver
 * @since 2024-01-01
 */
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
public class FaceDetectionApplicationIT {

    @LocalServerPort
    private int port;

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private FaceDetectionController faceDetectionController;

    @Autowired
    private FaceDetectionService faceDetectionService;

    @Test
    void contextLoads() {
        // 测试Spring上下文是否正确加载
        assertNotNull(faceDetectionController);
        assertNotNull(faceDetectionService);
    }

    @Test
    void testHealthCheckEndpoint() {
        // 测试健康检查接口
        String url = "http://localhost:" + port + "/face-detection/api/face/health";
        
        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
        
        assertEquals(HttpStatus.OK, response.getStatusCode());
        assertNotNull(response.getBody());
        assertTrue(response.getBody().contains("\"code\":200"));
        assertTrue(response.getBody().contains("人脸检测服务运行正常"));
    }

    @Test
    void testDetectFacesEndpoint_WithoutFile() {
        // 测试没有文件的人脸检测接口
        String url = "http://localhost:" + port + "/face-detection/api/face/detect";
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        
        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
        
        ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);
        
        // 应该返回400错误，因为没有提供图片文件
        assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
        assertNotNull(response.getBody());
    }

    @Test
    void testSwaggerUIAccess() {
        // 测试Swagger UI是否可访问
        String url = "http://localhost:" + port + "/face-detection/doc.html";
        
        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
        
        // Swagger UI应该返回200或重定向
        assertTrue(response.getStatusCode().is2xxSuccessful() || 
                  response.getStatusCode().is3xxRedirection());
    }

    @Test
    void testApplicationProperties() {
        // 测试应用配置是否正确加载
        String url = "http://localhost:" + port + "/actuator/health";
        
        try {
            ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
            // 如果actuator可用，应该返回健康状态
            if (response.getStatusCode().is2xxSuccessful()) {
                assertNotNull(response.getBody());
            }
        } catch (Exception e) {
            // 如果actuator未启用，这是正常的
            assertTrue(true);
        }
    }

    @Test
    void testCorsConfiguration() {
        // 测试CORS配置
        String url = "http://localhost:" + port + "/face-detection/api/face/health";
        
        HttpHeaders headers = new HttpHeaders();
        headers.setOrigin("http://localhost:3000");
        headers.add("Access-Control-Request-Method", "GET");
        
        HttpEntity<String> entity = new HttpEntity<>(headers);
        
        ResponseEntity<String> response = restTemplate.exchange(
                url, HttpMethod.OPTIONS, entity, String.class);
        
        // CORS预检请求应该被正确处理
        assertTrue(response.getStatusCode().is2xxSuccessful() || 
                  response.getStatusCode() == HttpStatus.FORBIDDEN);
    }

    @Test
    void testErrorHandling() {
        // 测试错误处理
        String url = "http://localhost:" + port + "/face-detection/api/face/nonexistent";
        
        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
        
        // 不存在的接口应该返回404
        assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
    }

    @Test
    void testContentTypeHandling() {
        // 测试内容类型处理
        String url = "http://localhost:" + port + "/face-detection/api/face/detect";
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        
        String jsonBody = "{\"test\": \"data\"}";
        HttpEntity<String> requestEntity = new HttpEntity<>(jsonBody, headers);
        
        ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);
        
        // 应该返回错误，因为接口期望multipart/form-data
        assertTrue(response.getStatusCode().is4xxClientError() || 
                  response.getStatusCode().is5xxServerError());
    }

    @Test
    void testLargeRequestHandling() {
        // 测试大请求处理
        String url = "http://localhost:" + port + "/face-detection/api/face/detect";
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        
        // 创建一个大的假文件
        byte[] largeData = new byte[10 * 1024 * 1024]; // 10MB
        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        body.add("image", largeData);
        
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
        
        try {
            ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);
            // 应该能处理大文件或返回适当的错误
            assertNotNull(response);
        } catch (Exception e) {
            // 如果有文件大小限制，这是正常的
            assertTrue(e.getMessage().contains("size") || 
                      e.getMessage().contains("limit") ||
                      e.getMessage().contains("too large"));
        }
    }

    @Test
    void testConcurrentRequests() throws InterruptedException {
        // 测试并发请求处理
        String url = "http://localhost:" + port + "/face-detection/api/face/health";
        
        Thread[] threads = new Thread[5];
        boolean[] results = new boolean[5];
        
        for (int i = 0; i < 5; i++) {
            final int index = i;
            threads[i] = new Thread(() -> {
                try {
                    ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
                    results[index] = response.getStatusCode().is2xxSuccessful();
                } catch (Exception e) {
                    results[index] = false;
                }
            });
            threads[i].start();
        }
        
        // 等待所有线程完成
        for (Thread thread : threads) {
            thread.join();
        }
        
        // 所有请求都应该成功
        for (boolean result : results) {
            assertTrue(result);
        }
    }

    @Test
    void testResponseFormat() {
        // 测试响应格式
        String url = "http://localhost:" + port + "/face-detection/api/face/health";
        
        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
        
        assertEquals(HttpStatus.OK, response.getStatusCode());
        assertNotNull(response.getBody());
        
        // 验证响应是JSON格式
        assertTrue(response.getBody().startsWith("{"));
        assertTrue(response.getBody().endsWith("}"));
        assertTrue(response.getBody().contains("\"code\""));
        assertTrue(response.getBody().contains("\"message\""));
        assertTrue(response.getBody().contains("\"data\""));
    }
} 